package com.lai.shop.service.impl;

import com.alibaba.cloud.context.utils.StringUtils;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.dingxianginc.ctu.client.CaptchaClient;
import com.dingxianginc.ctu.client.model.CaptchaResponse;
import com.lai.shop.config.ThirdPartyConfig;
import com.lai.shop.constant.RedisConstant;
import com.lai.shop.enums.StatusCodeEnum;
import com.lai.shop.exception.BizException;
import com.lai.shop.service.ThirdPartyService;
import com.lai.shop.vo.VerificationCodeVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service("thirdPartyService")
public class ThirdPartyServiceImpl implements ThirdPartyService {

    @Autowired
    OSS ossClient;

    @Autowired
    ThirdPartyConfig thirdPartyConfig;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Value("${spring.cloud.alicloud.oss.endpoint}")
    private String endpoint;

    @Value("${spring.cloud.alicloud.oss.bucket}")
    private String bucket;

    @Value("${spring.cloud.alicloud.access-key}")
    private String accessId;

    @Value("${third-party.sms.sign-name}")
    private String signName;

    @Value("${third-party.sms.template-code-default}")
    private String templateCodeDefault;

    /*@Value("${third-party.sms.template-code-password}")
    private String templateCodePassword;*/



    @Override
    public Map<String, String> ossPolicy() {
        //https://gulimall-lai.oss-cn-hangzhou.aliyuncs.com/%E9%9D%92%E8%9B%87.jpg
        //String bucket = "gulimall-lai"; // 请填写您的 bucketname 。
        String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint

        String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String dir = format + "/"; // 用户上传文件时指定的前缀。
        Map<String, String> respMap = null;
        try {
            long expireTime = 30;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            // PostObject请求最大可支持的文件大小为5 GB，即CONTENT_LENGTH_RANGE为5*1024*1024*1024。
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            respMap = new LinkedHashMap<String, String>();
            respMap.put("accessid", accessId);
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            respMap.put("dir", dir);
            respMap.put("host", host);
            respMap.put("expire", String.valueOf(expireEndTime / 1000));
            // respMap.put("expire", formatISO8601Date(expiration));
        } catch (Exception e) {
            // Assert.fail(e.getMessage());
            System.out.println(e.getMessage());
        } finally {
            ossClient.shutdown();
        }
        return respMap;
    }

    @Override
    public void sendVerificationCode(VerificationCodeVo verificationCodeVo) throws Exception {
        //验证token 顶象的图形验证码
        boolean response = graphValidate(verificationCodeVo.getToken());
        if(response){
            String randomCode = getRandomCode();
            String code = randomCode + "_" + System.currentTimeMillis();

            //根据电话获取redis的code
            String redisCode = redisTemplate.opsForValue().get(RedisConstant.SMS_PREFIX + verificationCodeVo.getMobile());
            //判断mobile在不在redis里面 如果在 并且时间过了60s，则可以继续发验证码
            if(!StringUtils.isEmpty(redisCode)){//redis 中存在
                //获取到当时存入的时间   转成long
                long fixTime = Long.parseLong(redisCode.split("_")[1]);
                //当前时间  -  当时存入的时间  小于  60000ms   则不能发送
                if(System.currentTimeMillis() - fixTime < 60000){
                    throw new BizException(StatusCodeEnum.FREQUENTLY_SEND_CODE);
                }
            }else{//不存在
                //发送验证码
                sms(verificationCodeVo.getMobile(), randomCode);
                //把验证码存入redis   5分钟有效
                redisTemplate.opsForValue().set(RedisConstant.SMS_PREFIX + verificationCodeVo.getMobile(),code,5, TimeUnit.MINUTES);
            }
        }else{
            throw new BizException("令牌验证错误");
        }

    }

    private void sms(String mobile, String randomCode) throws Exception {
        Client smsClient = thirdPartyConfig.createSmsClient();
        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                .setPhoneNumbers(mobile)
                .setSignName(signName)
                .setTemplateCode(templateCodeDefault)
                .setTemplateParam("{\"code\":"+ randomCode +"}");
        try {
            SendSmsResponse sendSmsResponse = smsClient.sendSms(sendSmsRequest);
            System.out.println(sendSmsResponse.getBody().getCode());
            System.out.println(sendSmsResponse.getBody().getMessage());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private boolean graphValidate(String token) throws Exception {
        CaptchaClient captchaClient = thirdPartyConfig.producer();
        captchaClient.setCaptchaUrl("http://vip6.dingxiang-inc.com/api/tokenVerify");
        CaptchaResponse response = captchaClient.verifyToken(token);
        //CaptchaResponse response = captchaClient.verifyToken(token, ip);
        //针对一些token冒用的情况，业务方可以采集客户端ip随token一起提交到验证码服务，验证码服务除了判断token的合法性还会校验提交业务参数的客户端ip和验证码颁发token的客户端ip是否一致
        //确保验证状态是SERVER_SUCCESS，SDK中有容错机制，在网络出现异常的情况会返回通过
        //System.out.println(response.getIp());
        //验证码服务采集到的客户端ip
        return response.getResult();
    }

    /**
     * 生成6位随机验证码
     *
     * @return 验证码
     */
    public static String getRandomCode() {
        StringBuilder str = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 6; i++) {
            str.append(random.nextInt(10));
        }
        return str.toString();
    }
}
